package services

import (
	"context"
	"fmt"
	"sync"
	"time"

	"go-agent/pkg/client"

	"github.com/sirupsen/logrus"
)

// IntervalSchedule 时间窗口调度配置
type IntervalSchedule struct {
	ItemID          int64  `json:"itemId"`          // 监控项ID
	IntervalStr     string `json:"intervalStr"`     // 间隔描述，如 "90s"
	IntervalSeconds int    `json:"intervalSeconds"` // 间隔秒数
	Week            int    `json:"week"`            // 星期几 (1-7: 1=周一, 7=周日)
	WeekStr         string `json:"weekStr"`         // 星期范围描述，如 "1-7"
	StartTime       string `json:"startTime"`       // 开始时间，如 "13:00:00"
	EndTime         string `json:"endTime"`         // 结束时间，如 "14:00:00" (支持跨日)
}

// CollectItem 采集项
type CollectItem struct {
	ItemID                int64              `json:"itemId"`                // 监控项ID
	ItemName              string             `json:"itemName"`              // 监控项名称
	ItemKey               string             `json:"itemKey"`               // 监控项键值
	InfoType              int                `json:"infoType"`              // 信息类型 (0:数值型, 1:字符型, 2:日志型)
	UpdateIntervalSeconds int                `json:"updateIntervalSeconds"` // 推送间隔(秒) - 默认间隔或窗口外间隔
	Timeout               int                `json:"timeout"`               // 采集超时时间(秒)
	Description           *string            `json:"description"`           // 监控项描述
	Intervals             []IntervalSchedule `json:"intervals"`             // 复杂时间调度配置数组
	ValueType             string             `json:"valueType,omitempty"`   // 值类型 (numeric, text, log)
	Units                 string             `json:"units,omitempty"`       // 单位
	Status                int                `json:"status,omitempty"`      // 状态 (0:启用, 1:禁用)
	Priority              int                `json:"priority,omitempty"`    // 优先级
	Tags                  map[string]string  `json:"tags,omitempty"`        // 标签
}

// ConfigManager 配置管理器
type ConfigManager struct {
	client         *client.DeviceMonitorClient
	logger         *logrus.Logger
	items          []CollectItem
	mutex          sync.RWMutex
	lastUpdate     time.Time
	refreshChan    chan struct{}
	stopChan       chan struct{}
	wg             sync.WaitGroup
	running        bool
	onConfigUpdate func([]CollectItem) // 配置更新回调
}

// ConfigManagerConfig 配置管理器配置
type ConfigManagerConfig struct {
	RefreshInterval time.Duration `mapstructure:"refresh_interval"`
	Enabled         bool          `mapstructure:"enabled"`
}

// NewConfigManager 创建配置管理器
func NewConfigManager(client *client.DeviceMonitorClient, logger *logrus.Logger, config *ConfigManagerConfig) *ConfigManager {
	refreshInterval := config.RefreshInterval
	if refreshInterval <= 0 {
		refreshInterval = 5 * time.Minute // 默认5分钟刷新一次
	}

	return &ConfigManager{
		client:      client,
		logger:      logger,
		items:       make([]CollectItem, 0),
		refreshChan: make(chan struct{}, 1),
		stopChan:    make(chan struct{}),
		running:     false,
	}
}

// SetConfigUpdateCallback 设置配置更新回调
func (cm *ConfigManager) SetConfigUpdateCallback(callback func([]CollectItem)) {
	cm.mutex.Lock()
	defer cm.mutex.Unlock()
	cm.onConfigUpdate = callback
}

// Start 启动配置管理器
func (cm *ConfigManager) Start(ctx context.Context) error {
	cm.mutex.Lock()
	defer cm.mutex.Unlock()

	if cm.running {
		return fmt.Errorf("配置管理器已在运行")
	}

	// 初始加载配置
	if err := cm.loadConfig(ctx); err != nil {
		cm.logger.Error("初始加载配置失败", map[string]interface{}{
			"error": err.Error(),
		})
		return err
	}

	cm.running = true
	cm.wg.Add(1)

	go cm.refreshLoop(ctx)

	cm.logger.Info("配置管理器已启动")
	return nil
}

// Stop 停止配置管理器
func (cm *ConfigManager) Stop() error {
	cm.mutex.Lock()
	defer cm.mutex.Unlock()

	if !cm.running {
		return nil
	}

	close(cm.stopChan)
	cm.running = false

	cm.wg.Wait()

	cm.logger.Info("配置管理器已停止")
	return nil
}

// GetItems 获取采集项列表
func (cm *ConfigManager) GetItems() []CollectItem {
	cm.mutex.RLock()
	defer cm.mutex.RUnlock()

	// 返回副本，避免外部修改
	items := make([]CollectItem, len(cm.items))
	copy(items, cm.items)
	return items
}

// GetItemByID 根据ID获取采集项
func (cm *ConfigManager) GetItemByID(itemID int64) (*CollectItem, error) {
	cm.mutex.RLock()
	defer cm.mutex.RUnlock()

	for _, item := range cm.items {
		if item.ItemID == itemID {
			return &item, nil
		}
	}

	return nil, fmt.Errorf("未找到采集项: %d", itemID)
}

// GetItemsByType 根据类型获取采集项
func (cm *ConfigManager) GetItemsByType(itemType string) []CollectItem {
	cm.mutex.RLock()
	defer cm.mutex.RUnlock()

	var items []CollectItem
	for _, item := range cm.items {
		if item.ItemKey == itemType {
			items = append(items, item)
		}
	}

	return items
}

// RefreshConfig 手动刷新配置
func (cm *ConfigManager) RefreshConfig() {
	select {
	case cm.refreshChan <- struct{}{}:
		cm.logger.Info("触发配置刷新")
	default:
		cm.logger.Debug("配置刷新已在队列中")
	}
}

// GetLastUpdateTime 获取最后更新时间
func (cm *ConfigManager) GetLastUpdateTime() time.Time {
	cm.mutex.RLock()
	defer cm.mutex.RUnlock()
	return cm.lastUpdate
}

// loadConfig 加载配置
func (cm *ConfigManager) loadConfig(ctx context.Context) error {
	cm.logger.Info("🔄 loadConfig: 开始加载采集配置")
	defer cm.logger.Info("🏁 loadConfig: 方法执行完毕")
	cm.logger.Debug("开始加载采集配置")

	cm.logger.Info("🌐 loadConfig: 调用API获取配置")
	resp, err := cm.client.GetConfig(ctx)
	if err != nil {
		cm.logger.Error("❌ loadConfig: API调用失败", map[string]interface{}{
			"error": err.Error(),
		})
		return fmt.Errorf("获取配置失败: %v", err)
	}

	cm.logger.Info("✅ loadConfig: API调用成功", map[string]interface{}{
		"response_code": resp.Code,
		"data_count":    len(resp.Data),
	})

	if resp.Code != 200 {
		return fmt.Errorf("获取配置响应异常: %s", resp.Msg)
	}

	// 转换响应数据为内部结构
	cm.logger.Debug("开始转换响应数据", map[string]interface{}{
		"data_count": len(resp.Data),
	})

	items := make([]CollectItem, len(resp.Data))
	for i, item := range resp.Data {
		cm.logger.Debug("转换监控项", map[string]interface{}{
			"index":                   i,
			"item_id":                 item.ItemID,
			"item_name":               item.ItemName,
			"item_key":                item.ItemKey,
			"update_interval_seconds": item.UpdateIntervalSeconds,
			"intervals_count":         len(item.Intervals),
		})

		intervals := convertIntervals(item.Intervals)
		cm.logger.Debug("转换间隔配置完成", map[string]interface{}{
			"item_id":         item.ItemID,
			"converted_count": len(intervals),
		})

		items[i] = CollectItem{
			ItemID:                item.ItemID,
			ItemName:              item.ItemName,
			ItemKey:               item.ItemKey,
			InfoType:              item.InfoType,
			UpdateIntervalSeconds: item.UpdateIntervalSeconds,
			Timeout:               item.Timeout,
			Description:           item.Description,
			Intervals:             intervals, // 转换intervals字段
			// 根据InfoType设置ValueType
			ValueType: inferValueType(item.InfoType),
			Units:     "",
			Status:    0, // 默认启用
			Priority:  1, // 默认优先级
			Tags:      make(map[string]string),
		}
	}
	cm.logger.Debug("数据转换完成", map[string]interface{}{
		"total_items": len(items),
	})

	// 更新配置
	cm.logger.Debug("🔄 开始更新配置", map[string]interface{}{
		"items_count": len(items),
	})

	// 使用临时作用域来管理锁
	var callback func([]CollectItem)
	func() {
		cm.logger.Debug("🔒 准备获取配置锁")
		cm.mutex.Lock()
		defer cm.mutex.Unlock()
		cm.logger.Debug("✅ 已获取配置锁")

		cm.items = items
		cm.lastUpdate = time.Now()
		cm.logger.Debug("📝 配置已更新到内存", map[string]interface{}{
			"update_time": cm.lastUpdate,
		})

		// 保存回调函数引用（避免在锁内调用）
		callback = cm.onConfigUpdate
		cm.logger.Debug("🔄 准备释放配置锁", map[string]interface{}{
			"callback_exists": callback != nil,
		})
		cm.logger.Debug("🔓 配置锁已释放")
	}()

	// 在锁外调用配置更新回调，避免死锁
	if callback != nil {
		cm.logger.Info("🚀 调用配置更新回调")
		go callback(items)
		cm.logger.Debug("📞 回调已异步启动")
	} else {
		cm.logger.Warn("⚠️ 配置更新回调为空")
	}

	cm.logger.Info("配置加载成功", map[string]interface{}{
		"item_count":  len(items),
		"update_time": cm.lastUpdate,
	})

	// 记录配置详情
	for _, item := range items {
		cm.logger.Debug("加载采集项", map[string]interface{}{
			"item_id":                 item.ItemID,
			"item_name":               item.ItemName,
			"item_key":                item.ItemKey,
			"info_type":               item.InfoType,
			"value_type":              item.ValueType,
			"update_interval_seconds": item.UpdateIntervalSeconds,
			"timeout":                 item.Timeout,
			"status":                  item.Status,
			"priority":                item.Priority,
		})
	}

	return nil
}

// refreshLoop 配置刷新循环
func (cm *ConfigManager) refreshLoop(ctx context.Context) {
	defer cm.wg.Done()

	ticker := time.NewTicker(30 * time.Minute) // 每30分钟自动刷新，降低频率
	defer ticker.Stop()

	for {
		select {
		case <-ctx.Done():
			cm.logger.Info("配置管理器因上下文取消而停止")
			return
		case <-cm.stopChan:
			cm.logger.Info("配置管理器收到停止信号")
			return
		case <-cm.refreshChan:
			if err := cm.loadConfig(ctx); err != nil {
				cm.logger.Error("手动刷新配置失败", map[string]interface{}{
					"error": err.Error(),
				})
			}
		case <-ticker.C:
			if err := cm.loadConfig(ctx); err != nil {
				cm.logger.Error("定时刷新配置失败", map[string]interface{}{
					"error": err.Error(),
				})
			}
		}
	}
}

// IsRunning 检查是否在运行
func (cm *ConfigManager) IsRunning() bool {
	cm.mutex.RLock()
	defer cm.mutex.RUnlock()
	return cm.running
}

// GetItemCount 获取采集项数量
func (cm *ConfigManager) GetItemCount() int {
	cm.mutex.RLock()
	defer cm.mutex.RUnlock()
	return len(cm.items)
}

// inferValueType 根据InfoType推断ValueType
func inferValueType(infoType int) string {
	switch infoType {
	case 0:
		return "numeric" // 数值型
	case 1:
		return "text" // 字符型
	case 2:
		return "log" // 日志型
	default:
		return "text" // 默认为文本类型
	}
}

// UpdateItemTags 更新监控项标签
func (cm *ConfigManager) UpdateItemTags(itemID int64, tags map[string]string) error {
	cm.mutex.Lock()
	defer cm.mutex.Unlock()

	for i, item := range cm.items {
		if item.ItemID == itemID {
			if cm.items[i].Tags == nil {
				cm.items[i].Tags = make(map[string]string)
			}
			// 合并标签
			for k, v := range tags {
				cm.items[i].Tags[k] = v
			}
			return nil
		}
	}

	return fmt.Errorf("未找到监控项: %d", itemID)
}

// GetItemsByStatus 根据状态获取采集项
func (cm *ConfigManager) GetItemsByStatus(status int) []CollectItem {
	cm.mutex.RLock()
	defer cm.mutex.RUnlock()

	var items []CollectItem
	for _, item := range cm.items {
		if item.Status == status {
			items = append(items, item)
		}
	}

	return items
}

// SetItemStatus 设置监控项状态
func (cm *ConfigManager) SetItemStatus(itemID int64, status int) error {
	cm.mutex.Lock()
	defer cm.mutex.Unlock()

	for i, item := range cm.items {
		if item.ItemID == itemID {
			cm.items[i].Status = status
			return nil
		}
	}

	return fmt.Errorf("未找到监控项: %d", itemID)
}

// convertIntervals 转换响应中的intervals字段为内部结构
func convertIntervals(respIntervals []client.IntervalScheduleResponse) []IntervalSchedule {
	if len(respIntervals) == 0 {
		return nil
	}

	intervals := make([]IntervalSchedule, len(respIntervals))
	for i, resp := range respIntervals {
		intervals[i] = IntervalSchedule{
			ItemID:          resp.ItemID,
			IntervalStr:     resp.IntervalStr,
			IntervalSeconds: resp.IntervalSeconds,
			Week:            resp.Week,
			WeekStr:         resp.WeekStr,
			StartTime:       resp.StartTime,
			EndTime:         resp.EndTime,
		}
	}

	return intervals
}
